--- @param extension Package
--- @param HY HY_Utility
--- @param U Utility
return function(extension, HY, U)
    local hy_kasodani_kyouko = General:new(extension, "hy_kasodani_kyouko", "jin_k", 4, 4, General.Female)
    local resonance = fk.CreateSkill {
        name = "resonance",
    }
    resonance:addEffect(fk.CardUseFinished, {
        anim_type = "control",
        can_trigger = function(self, event, target, player, data)
            local result = false
            if not player:hasSkill(resonance.name, true) then
                return false
            end
            if player:hasSkill(resonance.name) and data.card and data.card.color ~= Card.NoColor and data.card.extra_data and data.card.extra_data.resonance and not player:isNude() and
                table.any(data:getAllTargets(), function(t)
                    return not t.dead and player:canUseTo(data.card, t, { bypass_distances = true, bypass_times = true }) or t == player
                end) then
                if data.card.name == "collateral" then
                    if table.any(player.room:getOtherPlayers(player), function(t)
                            return t:inMyAttackRange(data:getSubTos(data.tos[1])[1]) and not not t:getEquipment(Card.SubtypeWeapon)
                        end) then
                        result = true
                    end
                else
                    result = true
                end
            end
            if data.card.extra_data then
                data.card.extra_data.resonance = nil
            end
            return result
        end,
        on_cost = function(self, event, target, player, data)
            local pattern = ".|.|"
            if data.card.color == Card.Black then
                pattern = pattern .. "spade,club"
            elseif data.card.color == Card.Red then
                pattern = pattern .. "heart,diamond"
            end
            local cards = player.room:askToCards(player, {
                min_num = 1,
                max_num = 1,
                include_equip = true,
                skill_name = resonance.name,
                pattern = pattern,
                prompt = "resonance_prompt:::" .. data.card.name
            })
            if type(cards) == "number" then
                cards = { cards }
            end
            if #cards > 0 then
                event:setCostData(self, cards)
                return true
            end
        end,
        on_use = function(self, event, target, player, data)
            local room = player.room
            room:throwCard(event:getCostData(self), resonance.name, player, player)
            local card = Fk:cloneCard(data.card.name)
            local targets = data:getAllTargets()
            local count = #targets
            local tos = {}
            if table.contains(targets, player) then
                local valid_targets = {}
                if card.name == "collateral" then
                    local slash_target = data:getSubTos(data.tos[1])[1]
                    valid_targets = table.filter(room.alive_players, function(t)
                        return t:inMyAttackRange(slash_target) and player:canUseTo(card, t, { bypass_distances = true, bypass_times = true,
                        }) and not t.dead
                    end)
                    local new_targets
                    if #valid_targets <= count then
                        new_targets = valid_targets
                    else
                        new_targets = room:askToChoosePlayers(player, {
                            targets = valid_targets,
                            min_num = count,
                            max_num = count,
                            skill_name = resonance.name,
                            prompt = "resonance_retarget_prompt",
                            cancelable = false,
                        })
                    end
                    tos = new_targets
                else
                    valid_targets = table.filter(room.alive_players, function(t)
                        return player:canUseTo(card, t, { bypass_distances = true, bypass_times = true }) and not t.dead
                    end)
                    if #valid_targets <= count then
                        tos = valid_targets
                    else
                        tos = room:askToChoosePlayers(player, {
                            targets = valid_targets,
                            min_num = count,
                            max_num = count,
                            skill_name = resonance.name,
                            prompt = "resonance_retarget_prompt",
                            cancelable = false
                        })
                    end
                end
            else
                tos = targets
            end
            local use = { ---@type UseCardDataSpec
                from = player,
                tos = {},
                card = card,
                extraUse = true,
                extra_data = {
                    bypass_distances = true,
                    bypass_times = true,
                },
            }
            if card.name == "collateral" then
                for i, t in ipairs(tos) do
                    use.tos[i * 2 - 1] = t
                    use.tos[i * 2] = data:getSubTos(data.tos[1])[1]
                end
            else
                for _, t in ipairs(tos) do
                    table.insertIfNeed(use.tos, t)
                end
            end
            if #use.tos > 0 then
                room:useCard(use)
            end
        end,
    })
    resonance:addEffect(fk.PreCardUse, {
        can_refresh = function(self, event, target, player, data)
            local room = player.room
            return player:hasSkill(resonance.name, true) and data.from and data.from == room.current and data.from ~= player and data.card:getEffectiveId() and
                (data.card.trueName == "slash" or data.card:isCommonTrick()) and
                #room.logic:getEventsOfScope(GameEvent.UseCard, 2, function(e)
                    local card = e.data.card
                    return card:getEffectiveId() and (card.trueName == "slash" or card:isCommonTrick()) and e.data.from and e.data.from == data.from
                end, Player.HistoryTurn) == 1
        end,
        on_refresh = function(self, event, target, player, data)
            data.card.extra_data = data.card.extra_data or {}
            data.card.extra_data.resonance = true
        end,
    })
    local echo = fk.CreateSkill {
        name = "echo",
    }
    echo:addEffect(fk.EventPhaseEnd, {
        anim_type = "drawcard",
        can_trigger = function(self, event, target, player)
            if player:hasSkill(echo.name) and target ~= player and target.phase == Player.Discard then
                local cards = player:getMark("echo_cards")
                for _, id in ipairs(cards) do
                    if player.room:getCardArea(id) ~= Card.DiscardPile then
                        table.removeOne(cards, id)
                    end
                end
                event:setCostData(self, cards)
                return #cards > 0
            end
        end,
        on_cost = function(self, event, target, player)
            local room = player.room
            if room:askToSkillInvoke(player, { skill_name = echo.name }) then
                local cards = event:getCostData(self)
                HY.AddCardsToTemp(player, cards)
                local cardId = HY.AskForCard(player, 1, 1, false, echo.name, true, ".|.|.|.|.|.|" ..
                    table.concat(cards, ","))
                HY.RemoveTempCards(player)
                if #cardId > 0 then
                    event:setCostData(self, cardId[1])
                    return true
                end
            end
        end,
        on_use = function(self, event, target, player)
            player.room:obtainCard(player, event:getCostData(self), true, fk.ReasonPrey)
        end,
    })
    echo:addEffect(fk.EventPhaseStart, {
        can_refresh = function(self, event, target, player, data)
            return player:hasSkill(echo.name) and target ~= player and target.phase == Player.Discard
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            room:setPlayerMark(player, "echo_cards", {})
        end
    })
    echo:addEffect(fk.AfterCardsMove, {
        can_refresh = function(self, event, target, player, data)
            return player:hasSkill(echo.name) and player.room.current.phase == Player.Discard and player.room.current ~= player
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            local cards = player:getMark("echo_cards")
            for _, move in ipairs(data) do
                if move.moveReason == fk.ReasonDiscard and move.from == room.current then
                    for _, info in ipairs(move.moveInfo) do
                        table.insertIfNeed(cards, info.cardId)
                    end
                end
                for _, info in ipairs(move.moveInfo) do
                    if info.fromArea == Card.DiscardPile then
                        table.removeOne(cards, info.cardId)
                    end
                end
            end
            room:setPlayerMark(player, "echo_cards", cards)
        end
    })
    extension:loadSkillSkels { resonance, echo }
    hy_kasodani_kyouko:addSkill("resonance")
    hy_kasodani_kyouko:addSkill("echo")
    Fk:loadTranslationTable {
        ["hy_kasodani_kyouko"] = "幽谷响子",
        ["#hy_kasodani_kyouko"] = "再翻译式回音",
        ["illustrator:hy_kasodani_kyouko"] = "nal",
        ["designer:hy_kasodani_kyouko"] = "黑曜人形",
        ["cv:hy_kasodani_kyouko"] = "",

        ["resonance"] = "共振",
        [":resonance"] = "在其他角色于其回合内使用的首张非虚拟【杀】或普通锦囊牌结算结束后，你可以弃置一张颜色相同的牌，然后视为对相同目标使用一张相同牌名的牌（若此牌指定的目标包含你，你须重新指定等量的目标）。",
        ["resonance_prompt"] = "共振：你可以弃置一张颜色相同的牌，视为对相同目标使用一张%arg",
        ["resonance_retarget_prompt"] = "共振：你须重新指定目标",

        ["echo"] = "回响",
        [":echo"] = "其他角色的弃牌阶段结束时，你可以获得一张其于本阶段弃置的牌。",
    }
end
